
#include "GroundAttackSequenceDecorator.h"

static const int GroundAttackingInterval = 240*1;
void GroundAttackSequenceDecorator::Enter()
{
	behavior->Enter();
	std::list<Base*>* bases = BB->GetBases();
	DEBUG_PRINT("GroundAttack(%p) executing.\n", this);

	if(findNearestEnemyBuilding())
		BB->SetAttackPosition(currentTargetTile);
	else if(bases)
	{
		if(bases->size() > 0)
			BB->SetAttackPosition(bases->back()->GetBaseLocation() + BWAPI::TilePosition(rand()%5,rand()%4));
	}
	
}

void GroundAttackSequenceDecorator::Exit()
{
	behavior->Exit();
	lastGroundAttackFrame = BWAPI::Broodwar->getFrameCount();
}

bool GroundAttackSequenceDecorator::CheckConditions()
{
	bool status = true;

	std::list<Base*>* bases = BB->GetBases();
	std::list<BWAPI::Unit*>* marines = BB->GetUnitsByTypeGeneral(BWAPI::UnitTypes::Terran_Marine);
	std::list<BWAPI::Unit*>* bats = BB->GetUnitsByTypeGeneral(BWAPI::UnitTypes::Terran_Firebat);
	if(!marines)
		return false;
	DEBUG_PRINT("CheckConditions GroundAttack, found %d marines\n", marines->size());

	int batSize = 0;
	if(bats)
		batSize += bats->size();
	// only GroundAttack once we get some critical mass of marines
	int multiplier = (bases) ? ((bases->size() > 1) ? 2 : 1) : 1;
	if(marines->size() + batSize  < 22 * multiplier)
		return false;

	if(lastGroundAttackFrame<0 || (BWAPI::Broodwar->getFrameCount() - lastGroundAttackFrame >= GroundAttackingInterval))
	{
		status |= true;
	}
	else
		status |= false;

	return status && behavior->CheckConditions();
}

bool GroundAttackSequenceDecorator::findNearestEnemyBuilding()
{
	int distance = INT_MAX;
	int temp;
	BWAPI::TilePosition currentTarget(0,0);
	std::map<BWAPI::UnitType,std::list<BWAPI::TilePosition>>* buildings = BB->GetEnemyBuildingLocations();
	if( BB->GetEnemyBases())
	{
		if( BB->GetEnemyBases()->size() > 0)
		{
			currentTargetTile = currentTarget = BB->GetEnemyBases()->front()->GetBaseLocation();
		}
		else if(buildings)
		{
			if(buildings->size() > 0)
			{
				for(std::map<BWAPI::UnitType,std::list<BWAPI::TilePosition>>::iterator it = buildings->begin(); it != buildings->end(); it++)
				{
					for(std::list<BWAPI::TilePosition>::iterator build = it->second.begin(); build != it->second.end(); build++)
					{
						currentTargetTile = currentTarget = *build;
						break;
					}
				}
			}
		}
	}
	else
	{
		std::list<Base*>* bases =  BB->GetBases();
		if(bases)
		{
			if(bases->size() > 0)
				currentTarget = bases->back()->GetBaseLocation();
		}
	}
	
	if(buildings)
	{
		if(buildings->size() > 0)
		{
			for(std::map<BWAPI::UnitType,std::list<BWAPI::TilePosition>>::iterator it = buildings->begin(); it != buildings->end(); it++)
			{
				for(std::list<BWAPI::TilePosition>::iterator build = it->second.begin(); build != it->second.end(); build++)
				{
					if(currentTarget != (*build))
					{
						temp = (*build).getDistance(currentTarget);
						if(temp < distance)
						{
							temp = distance;
							currentTarget = *build;
						}
					}
				}
			}
			currentTargetTile = currentTarget;
		}
	}
	if(currentTarget != BWAPI::TilePosition(0,0))
		return true;
	else
		return false;
}
